package services

import scala.xml.Node

import models.ModelXML
import play.api.libs.ws.Response
import play.api.libs.ws.WS
import play.api.Logger

trait GenericService[E <: ModelXML[E]] {

  val nomeEntidade: String
  val urlPadraoServicos = "http://localhost:8080/eEticaTCWS/"

  def toObject(node: Node): E

  private def service(resource: String, metodo: String, contentType: String = null, contentBody: Any = null, params: Map[String, String] = Map()): Option[Response] = {
    val url = urlPadraoServicos + nomeEntidade + resource
    val requestUrl = WS.WSRequestHolder(url, Map(), params, None, None)
    val requestContentType = if (contentType != null) requestUrl.withHeaders(("Content-Type", contentType)) else requestUrl
    try {
      metodo match {
        case "post" => {
          Some(requestContentType.post(contentBody.toString).value.get)
        }
        case "put" => {
          Some(requestContentType.put(contentBody.toString).value.get)
        }
        case "get" => {
          Some(requestContentType.get().value.get)
        }
        case "delete" => {
          Some(requestContentType.delete().value.get)
        }
        case _ => {
          Logger.error("Método inexistente!")
          None
        }
      }
    } catch {
      case e: Exception => {
    	Logger.error("Service Error: " + e.getMessage)
        None
      }
    }
  }
  
  def create(entidade: ModelXML[E]): E = {
    val response = service("/cadastrar", "post", "text/xml", entidade.toXml).getOrElse(throw new Exception("Erro na requisição"))
    toObject(response.xml)
  }

  def update(entidade: ModelXML[E]): E = {
    val response = service("/atualizar", "put", "text/xml", entidade.toXml).getOrElse(throw new Exception("Erro na requisição"))
    toObject(response.xml)
  }
  
  def delete(id: Int): Unit = {
    service("/remover", "delete", params = Map("id" -> id.toString))
  }
  
  def list(): List[E] = {
    val response = service("/listar", "get").getOrElse(throw new Exception("Erro na requisição"))
    val xml = response.xml
    val seq = for(node <- (xml \\ nomeEntidade)) yield toObject(node)
    seq.toList
  }
  
  def getById(id: Any): E = {
    val response = service("/", "get", params = Map("id" -> id.toString)).getOrElse(throw new Exception("Erro na requisição"))
    val xml = response.xml
    toObject((xml \\ nomeEntidade).head)
  }

}